package stone926.mods.more_enchantments.mixins;

import net.minecraft.entity.LivingEntity;
import net.minecraft.entity.ai.RangedAttackMob;
import net.minecraft.entity.ai.goal.BowAttackGoal;
import net.minecraft.entity.ai.goal.Goal;
import net.minecraft.entity.mob.HostileEntity;
import net.minecraft.entity.projectile.ProjectileUtil;
import net.minecraft.item.Item;
import net.minecraft.item.Items;
import net.minecraft.util.Hand;
import org.spongepowered.asm.mixin.Final;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.Redirect;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
import stone926.mods.more_enchantments.MoreEnchantmentsMod;
import stone926.mods.more_enchantments.items.bow.StoneBow;

@Mixin(BowAttackGoal.class)
public abstract class BowAttackGoalMixin<T extends HostileEntity & RangedAttackMob> extends Goal {

  @Shadow
  @Final
  private T actor;

  @Inject(method = "isHoldingBow", at = @At("RETURN"), cancellable = true)
  protected void isHoldingBow(CallbackInfoReturnable<Boolean> cir) {
    cir.setReturnValue(
      cir.getReturnValue()
        || actor.isHolding(MoreEnchantmentsMod.WITHER_SKULL_BOW)
        || actor.isHolding(MoreEnchantmentsMod.FIREBALL_BOW)
        || actor.isHolding(MoreEnchantmentsMod.SHULKER_BOW)
    );
  }

  @Redirect(method = "tick", at = @At(value = "INVOKE", target = "Lnet/minecraft/entity/projectile/ProjectileUtil;getHandPossiblyHolding(Lnet/minecraft/entity/LivingEntity;Lnet/minecraft/item/Item;)Lnet/minecraft/util/Hand;"))
  public Hand getHandPossiblyHolding(LivingEntity entity, Item item) {
    Hand hand = ProjectileUtil.getHandPossiblyHolding(entity, Items.BOW);
    if ((entity.getMainHandStack().getItem() instanceof StoneBow)
      || (entity.getMainHandStack().isEmpty() && entity.getOffHandStack().getItem() instanceof StoneBow)) {
      hand = Hand.MAIN_HAND;
    }
    return hand;
  }

}
